#include "stdafx.h"
#include "two-strings.h"
#include <unordered_set>
#include <algorithm>

std::unordered_set<char> calcCharSetOfStringSTL(const std::string &str) {
    std::unordered_set<char> result{};
    std::for_each(str.begin(), str.end(), [&result](const char &ch) { result.insert(ch); });
    return result;
}

std::string slnSTL(std::string s1, std::string s2)
{
    std::unordered_set<char> charSetOfS1 = calcCharSetOfStringSTL(s1);
    std::unordered_set<char> charSetOfS2 = calcCharSetOfStringSTL(s2);

    auto it1 = std::find_if(
        charSetOfS1.begin(),
        charSetOfS1.end(),
        [&charSetOfS2](const char &ch) {
            return charSetOfS2.find(ch) != charSetOfS2.end();
        }
    );
    return it1 != charSetOfS1.end() ? "YES" : "NO";
}

/*********************************************************************************
 * slnRaw
**********************************************************************************/
std::unordered_set<char> calcCharSetOfStringRaw(const std::string &str) {
    ptrdiff_t const strLen = str.size();
    std::unordered_set<char> results;

    // loop invariant:
    // results is the chars in range [0, i)
    for (ptrdiff_t i = 0; i < strLen; ++i) {
        results.insert(str[i]);
    }
    // post condition:
    // results is the chars in range [0, strLen)

    return results;
}

std::string slnRaw(std::string s1, std::string s2)
{
    std::unordered_set<char> const charSetOfS1 = calcCharSetOfStringRaw(s1);
    std::unordered_set<char> const charSetOfS2 = calcCharSetOfStringRaw(s2);

    // loop invariant
    // [charSetOfS1.begin(), it1) has done
    for (auto it1 = charSetOfS1.begin(); it1 != charSetOfS1.end(); ++it1) {
        char const ch1 = *it1;
        // loop invariant:
        // [charSetOfS2.begin(), it2) has done
        for (auto it2 = charSetOfS2.begin(); it2 != charSetOfS2.end(); ++it2) {
            char const ch2 = *it2;
            if (ch1 == ch2) {
                return "YES";
            }
        }
        // post condition:
        // [charSetOfS2.begin(), charSetOfS2.end()) has done
    }
    // post condition:
    // [charSetOfS1.begin(), charSetOfS1.end()) has done
    return "NO";
}
